home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Libraries / PixMaps 1.1 / Example / CSApp.c next >
Encoding:
C/C++ Source or Header  |  1997-07-10  |  15.7 KB  |  558 lines  |  [TEXT/MPS ]

  1. /* file CSApp.c Copyright (C) 1996,1997 by John R. Montbriand.  All Rights Reserved.
  2.     callback skeleton application, implementation.
  3.     Copyright (c) 1996, 1997 by John Montbriand.  All Rights Reserved.
  4.     Permission hereby granted for public use.
  5.         Distribute freely in areas where the laws of copyright apply.
  6.     USE AT YOUR OWN RISK.
  7.     DO NOT DISTRIBUTE MODIFIED COPIES.
  8.     Comments/questions/postcards* to the author at the address:
  9.       John Montbriand
  10.       P.O. Box. 1133
  11.       Saskatoon Saskatchewan Canada
  12.       S7K 3N2
  13.     or by email at:
  14.       tinyjohn@sk.sympatico.ca
  15.     *if you mail a postcard, then I will provide you with technical support
  16.     regarding questions you may have about this file.
  17. */
  18.  
  19. #include "CSApp.h"
  20. #include <Traps.h>
  21. #include <OSUtils.h>
  22. #include <ToolUtils.h>
  23. #include <Events.h>
  24. #include <Fonts.h>
  25. #include <Gestalt.h>
  26. #include <SegLoad.h>
  27. #include <Resources.h>
  28.  
  29. QDGlobals    qd;
  30. static Boolean gWNE = false;
  31. static Boolean gAPPLEVENTS = false;
  32.  
  33. OSErr GotReqParam(const AppleEvent *apple_event) {
  34.     DescType retType;
  35.     Size actSize;
  36.     OSErr err;
  37.     err = AEGetAttributePtr(apple_event, keyMissedKeywordAttr, typeWildCard, &retType, NULL, 0, &actSize);
  38.     if (err == errAEDescNotFound)
  39.         return noErr;
  40.     else if (err == noErr)
  41.         return errAEEventNotHandled;
  42.     else return err;
  43. }
  44.  
  45. static unsigned short NumToolboxTraps(void) {
  46.     if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  47.         return 0x0200;
  48.     else return 0x0400;
  49. }
  50.  
  51. static TrapType FindTrapType(unsigned short theTrap) {
  52.     if (theTrap & 0x0800)
  53.         return ToolTrap;
  54.     else return OSTrap;
  55. }
  56.  
  57. Boolean TrapAvail(unsigned short theTrap) {
  58.     unsigned short localTrap = theTrap;
  59.     TrapType tType = FindTrapType(localTrap);
  60.     if ( tType == ToolTrap ) {
  61.         localTrap &= 0x07FF;
  62.         if ( localTrap >= NumToolboxTraps() )
  63.             localTrap = _Unimplemented;
  64.     }
  65.     return NGetTrapAddress(localTrap, tType) != NGetTrapAddress(_Unimplemented, ToolTrap);
  66. }
  67.  
  68.  
  69.  
  70.     /* MENU ROUTINES */
  71. static MenuResetFunc gMenuReset = NULL;
  72. static MenuHandlerFunc gMenuHandler = NULL;
  73.  
  74. OSErr SetMenuFunctions(short menubarID, MenuResetFunc reset, MenuHandlerFunc handler) {
  75.     Handle menu_bar;
  76.     gMenuReset = reset;
  77.     gMenuHandler = handler;
  78.     if (menubarID == 0) return noErr;
  79.     if ((menu_bar = GetNewMBar(menubarID)) == NULL) return resNotFound;
  80.     ClearMenuBar();
  81.     SetMenuBar(menu_bar);
  82.     DrawMenuBar();
  83.     return noErr;
  84. }
  85.  
  86.  
  87.  
  88.     /* DIALOG ROUTINES */
  89. static DialogEventFunc gDialogEvent = NULL;
  90. static DialogHitFunc gDialogHit = NULL;
  91. static EditDialogFunc gEditDialog = NULL;
  92.  
  93. void SetDialogFunctions(DialogEventFunc evtproc, DialogHitFunc hitproc, EditDialogFunc edit) {
  94.     gDialogEvent = evtproc;
  95.     gDialogHit = hitproc;
  96.     gEditDialog = edit;
  97. }
  98.  
  99. void DialogEdit(short itemno) {
  100.     WindowPtr target;
  101.     if ((target = FrontWindow()) == NULL) return;
  102.     if (GetWindowKind(target) != dialogKind) return;
  103.     switch (itemno) {
  104.         case iCut: DialogCut(target); break;
  105.         case iCopy: DialogCopy(target); break;
  106.         case iPaste: DialogPaste(target); break;
  107.         case iClear: DialogDelete(target); break;
  108.     }
  109. }
  110.  
  111.  
  112.  
  113. #pragma options align=mac68k
  114.  
  115. typedef struct {
  116.     Handle handle;     /* handle or procedure pointer for this item */
  117.     Rect bounds;     /* display rectangle for this item */
  118.     unsigned char type;       /* item type - 1 */
  119.     unsigned char data[1];    /* length byte of data */
  120. } DialogItem, *DialogItemPtr, **DialogItemHandle;
  121.  
  122. typedef struct {
  123.     short        max_index; /* number of items - 1 */
  124.     DialogItem    items[1]; /* first item in the array */
  125. } ItemList, *ItemListPtr, **ItemListHandle;
  126.  
  127. #pragma options align=reset
  128.  
  129. /* DialogAppendItems appends the DITL with the given id to the end of
  130.     the items in dialog resizing the window as necessary to accomodate
  131.     the new items.  if first_item != NULL, it is set to the index
  132.     of the first appended item. */
  133. OSErr DialogAppendItems(DialogPtr dialog, short id, short *first_item) {
  134.     long response;
  135.     
  136.         /* parameter checking */
  137.     if (dialog == NULL) return paramErr;
  138.  
  139.         /* use new calls, if they're in place */
  140.     if (Gestalt(gestaltDITLExtAttr, &response) != noErr) response = 0;
  141.     if ((response & (1<<gestaltDITLExtPresent)) != 0) {
  142.         Handle the_ditl;
  143.         if ((the_ditl = GetResource('DITL', id)) == NULL) return resNotFound;
  144.         if (first_item != NULL) *first_item = CountDITL(dialog) + 1;
  145.         AppendDITL(dialog, the_ditl, appendDITLBottom);
  146.         ReleaseResource(the_ditl);
  147.         return noErr;
  148.     } else {
  149.         Point offset;
  150.         Rect max_rect;
  151.         ItemListHandle itms, actitms; /* handle to DITL being appended */
  152.         DialogItemPtr item; /* pointer to item being appended */
  153.         short new_items, data_size, i;
  154.         OSErr err;
  155.         itms = (ItemListHandle) GetResource('DITL', id);
  156.         if (itms == NULL) { err = resNotFound; goto bail; }
  157.             /* collect the information we'll be using */
  158.         max_rect = dialog->portRect;
  159.         SetPt(&offset, 0, max_rect.bottom);
  160.         max_rect.bottom -= 5; max_rect.right -= 5;
  161.         actitms = (ItemListHandle) ((DialogPeek)dialog)->items;
  162.         if (first_item != NULL) *first_item = (*actitms)->max_index + 2;
  163.         HLock((Handle)itms);
  164.         new_items = (*itms)->max_index + 1;
  165.             /* build the new items */
  166.         for (item = (*itms)->items, i = 0; i < new_items; i++ ) {
  167.             OffsetRect(&item->bounds, offset.h, offset.v);
  168.             UnionRect(&item->bounds, &max_rect, &max_rect);
  169.             switch ( item->type & 0x7F ) {
  170.                 case ctrlItem + btnCtrl: case ctrlItem + chkCtrl: case ctrlItem + radCtrl:
  171.                     item->handle = (Handle) NewControl((DialogPtr) dialog, &item->bounds,
  172.                         (StringPtr)item->data, true, 0, 0, 1, item->type & 0x03, 0);
  173.                     break;
  174.                 case ctrlItem + resCtrl:
  175.                     item->handle = (Handle) GetNewControl(*(short*)(item->data + 1), (DialogPtr) dialog);
  176.                     (*(ControlHandle)item->handle)->contrlRect = item->bounds;
  177.                     break;
  178.                 case statText: case editText:
  179.                     if ((err = PtrToHand(item->data + 1, &item->handle, item->data[0])) != noErr) goto bail;
  180.                     break;
  181.                 case iconItem:
  182.                     item->handle = GetIcon(*(short*)(item->data + 1));
  183.                     break;
  184.                 case picItem:
  185.                     item->handle = (Handle) GetPicture(*(short*)(item->data + 1));
  186.                     break;
  187.                 default: item->handle = NULL; break;
  188.             }
  189.             data_size = (item->data[0] + 1) & 0xFFFE;
  190.             item = (DialogItemPtr)((char*)item + data_size + sizeof(DialogItem));
  191.         }
  192.         if ((err = PtrAndHand((*itms)->items, (Handle)actitms, GetHandleSize((Handle) itms) - 2)) != noErr) goto bail;
  193.         (*actitms)->max_index += new_items;
  194.         HUnlock((Handle) itms);
  195.         ReleaseResource((Handle) itms);
  196.         max_rect.bottom += 5; max_rect.right += 5;
  197.         SizeWindow((WindowPtr) dialog, max_rect.right, max_rect.bottom, true);
  198.         return noErr;
  199.     bail:
  200.         if (itms != NULL) {
  201.             HUnlock((Handle) itms);
  202.             ReleaseResource((Handle) itms);
  203.         }
  204.         return err;
  205.     }
  206. }
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.     /* WINDOW ROUTINES */
  215. static CloseWindowFunc gCloseWindow = NULL;
  216. static GrowWindowFunc gGrowWindow = NULL;
  217. static ZoomWindowFunc gZoomWindow = NULL;
  218. static ClickWindowFunc gClickWindow = NULL;
  219. static unsigned long gLastClickTime = 0;
  220. static short gClickCounter = 0;
  221. static ActivateWindowFunc gActivateWindow = NULL;
  222. static UpdateWindowFunc gUpdateWindow = NULL;
  223. static EditWindowFunc gEditWindow = NULL;
  224. static WindowPtr gTheActiveWindow = NULL;
  225.  
  226. void SafeCloseWindow(WindowPtr window) {
  227.     if (window == gTheActiveWindow && gActivateWindow) {
  228.         gActivateWindow(window, false);
  229.         gTheActiveWindow = NULL;
  230.     }
  231.     CloseWindow(window);
  232. }
  233.  
  234. void SafeDisposeWindow(WindowPtr window) {
  235.     if (window == gTheActiveWindow && gActivateWindow) {
  236.         gActivateWindow(window, false);
  237.         gTheActiveWindow = NULL;
  238.     }
  239.     DisposeWindow(window);
  240. }
  241.  
  242. void SetWindowManipulators(CloseWindowFunc close, GrowWindowFunc grow, ZoomWindowFunc zoom) {
  243.     gCloseWindow = close;
  244.     gGrowWindow = grow;
  245.     gZoomWindow = zoom;
  246. }
  247.  
  248. void SetWindowInteraction(ClickWindowFunc click, EditWindowFunc edit) {
  249.     gClickWindow = click;
  250.     gEditWindow = edit;
  251. }
  252.     
  253. void SetWindowRedraw(ActivateWindowFunc activate, UpdateWindowFunc update) {
  254.     gActivateWindow = activate;
  255.     gUpdateWindow = update;
  256. }
  257.  
  258.  
  259. static Rect* GetMaxDeviceRect(Rect *globalRect, Rect* maxDevRect) {
  260.     GrafPtr mainPort;
  261.     long response, maxArea, area;
  262.     GDHandle device, mainDevice;
  263.     Rect sect;
  264.     if (Gestalt(gestaltQuickdrawVersion, &response) != noErr) response = 0;
  265.     if (response >= gestalt8BitQD) {
  266.         mainDevice = GetMainDevice();
  267.         maxArea = 0;
  268.         for (device = GetDeviceList(); device != NULL; device = GetNextDevice(device)) {
  269.             if (TestDeviceAttribute(device, screenDevice)
  270.               && TestDeviceAttribute(device, screenActive)
  271.               && SectRect(globalRect, &((*device)->gdRect), §)) {
  272.                 area = ((long) (sect.right - sect.left)) * ((long) (sect.bottom - sect.top));
  273.                 if (area > maxArea) {
  274.                     *maxDevRect = (*device)->gdRect;
  275.                     if (device == mainDevice)
  276.                         maxDevRect->top += GetMBarHeight();
  277.                     maxArea = area;
  278.                 }
  279.             }
  280.         }
  281.     } else {
  282.         GetWMgrPort(&mainPort);
  283.         *maxDevRect = mainPort->portRect;
  284.         maxDevRect->top += GetMBarHeight();
  285.     }
  286.     return maxDevRect;
  287. }
  288.  
  289.  
  290. void ZoomWindowToSize(WindowPtr window, short width, short height, short zoomDir) {
  291.     Rect standard, global, device;
  292.         /* erase the window */
  293.     SetPort(window);
  294.     EraseRect(&window->portRect);
  295.         /* find the window's monitor coordinates */
  296.     global = window->portRect;
  297.     LocalToGlobal((Point*) &global.top);
  298.     LocalToGlobal((Point*) &global.bottom);
  299.     GetMaxDeviceRect(&global, &device);
  300.         
  301.         /* calculate the new coordinates */
  302.     standard.top = device.top + 30;
  303.     standard.left = device.left + 20;
  304.     if ((standard.bottom = device.top + 30 + height) > device.bottom - 10) standard.bottom = device.bottom - 10;
  305.     if ((standard.right = device.left + 20 + width) > device.right - 10) standard.right = device.right - 10;
  306.             
  307.         /* install the new coordinates */
  308.     if (zoomDir == inZoomOut)
  309.         SetWindowStandardState(window, &standard);
  310.     else SetWindowUserState(window, &standard);
  311.     ZoomWindow(window, zoomDir, true);
  312. }
  313.  
  314.  
  315. void CallEditCommand(short editcmd) {
  316.     if (!SystemEdit(editcmd-1)) {
  317.         WindowPtr target;
  318.         if ((target = FrontWindow()) != NULL) {
  319.             if (GetWindowKind(target) == dialogKind) {
  320.                 if (gEditDialog)
  321.                     gEditDialog(target, editcmd);
  322.                 else DialogEdit(editcmd);
  323.             } else if (gEditWindow)
  324.                 gEditWindow(target, editcmd);
  325.         }
  326.     }
  327. }
  328.  
  329.     /* keydown callback */
  330. static KeyboardFunc gKeyboard = NULL;
  331. void SetKeyboardHook(KeyboardFunc keys) {
  332.     gKeyboard = keys;
  333. }
  334.  
  335.     /* MISC ROUTINES */
  336. static DiskInsertFunc gDiskInsert = NULL;
  337. static EventHookFunc gEventHook = NULL;
  338. static SwitcherFunc gSwitcher = NULL;
  339.  
  340. void SetMiscFunctions(DiskInsertFunc disk, EventHookFunc hook, SwitcherFunc switcher) {
  341.     gDiskInsert = disk;
  342.     gEventHook = hook;
  343.     gSwitcher = switcher;
  344. }
  345.  
  346.  
  347.     /* MOVEABLE MODAL ROUTINES */
  348. static WindowPtr gMMWindow = NULL;
  349. static MMHookFunc gMMHook = NULL;
  350.  
  351. void SetMMHookProc(MMHookFunc mmhook) {
  352.     gMMHook = mmhook;
  353. }
  354.  
  355. WindowPtr GetMMWindow(void) {
  356.     return gMMWindow;
  357. }
  358.  
  359. WindowPtr SetMMWindow(WindowPtr target) {
  360.     WindowPtr old_mmwind;
  361.     old_mmwind = gMMWindow;
  362.     gMMWindow = target;
  363.     if (gMMHook) {
  364.         int hasold, hasnew;
  365.         hasold = ((old_mmwind != NULL) ? 1 : 0);
  366.         hasnew = ((target != NULL) ? 1 : 0);
  367.         if ((hasold ^ hasnew) != 0)
  368.             gMMHook(hasnew);
  369.     }
  370.     return old_mmwind;
  371. }
  372.  
  373.  
  374.     /* MAIN DRIVER */
  375. void CSAppEvent(EventRecord *ev) {
  376.     WindowPtr target;
  377.     DialogPtr the_dialog;
  378.     short item_hit, part_code;
  379.     Boolean activate;
  380.     long menuresult;
  381.         
  382.         /* call our hook function */
  383.     if (gEventHook) if (gEventHook(ev)) return;
  384.         
  385.         /* is it a menu command? */
  386.     if ((ev->what == keyDown || ev->what == autoKey) && (ev->modifiers & cmdKey) != 0) {
  387.         if (gMenuReset) gMenuReset();
  388.         menuresult = MenuKey((short) (ev->message & charCodeMask));
  389.         if (gMenuHandler && HiWord(menuresult) != 0)
  390.             gMenuHandler(HiWord(menuresult), LoWord(menuresult), ev->modifiers, GetMHandle(HiWord(menuresult)));
  391.         ev->what = nullEvent;
  392.     }
  393.  
  394.         /* are we switching? */
  395.     if (ev->what == osEvt && ((ev->message >> 24) & 0x0FF) == suspendResumeMessage) {
  396.         activate = (ev->message & resumeFlag) != 0;
  397.         target = FrontWindow();
  398.         if (gActivateWindow && target) {
  399.             gActivateWindow(target, activate);
  400.             if (activate) gTheActiveWindow = target;
  401.         }
  402.         if (gSwitcher) gSwitcher(activate);
  403.     }
  404.  
  405.         /* preprocess for dialogs if it applies */
  406.     if (ev->what == activateEvt || ev->what == updateEvt)
  407.         target = (WindowPtr) ev->message;
  408.     else target = FrontWindow();
  409.     if (target && gDialogEvent)
  410.         if (GetWindowKind(target) == dialogKind)
  411.             gDialogEvent(target, ev);
  412.  
  413.         /* dispatch the event to the appropriate handler. */
  414.     if (IsDialogEvent(ev)) {
  415.         if (DialogSelect(ev, &the_dialog, &item_hit))
  416.             if (gDialogHit) gDialogHit(the_dialog, item_hit, ev->modifiers);
  417.     } else switch (ev->what) {
  418.         case keyDown:
  419.         case autoKey:
  420.             if (gKeyboard) gKeyboard((char) (ev->message & charCodeMask), ev);
  421.         case diskEvt:
  422.             if (gDiskInsert) gDiskInsert(ev);
  423.             break;
  424.         case mouseDown:
  425.             part_code = FindWindow(ev->where, &target);
  426.             switch (part_code) {
  427.                 case inMenuBar:
  428.                     if (gMenuReset) gMenuReset();
  429.                     menuresult = MenuSelect(ev->where);
  430.                     if (gMenuHandler && HiWord(menuresult) != 0)
  431.                         gMenuHandler(HiWord(menuresult), LoWord(menuresult), ev->modifiers, GetMHandle(HiWord(menuresult)));
  432.                     break;
  433.                 case inSysWindow:
  434.                     SystemClick(ev, target);
  435.                     break;
  436.                 case inGoAway:
  437.                     if (TrackGoAway(target, ev->where) && gCloseWindow)
  438.                         gCloseWindow(target);
  439.                     break;
  440.                 case inDrag:
  441.                     if ((GetMMWindow() != NULL) && (target != FrontWindow())) {
  442.                         SysBeep(1);
  443.                     } else {
  444.                         Rect boundsRect;
  445.                         boundsRect = qd.screenBits.bounds;
  446.                         InsetRect(&boundsRect, 4, 4);
  447.                         boundsRect.top += GetMBarHeight();
  448.                         DragWindow(target, ev->where, &boundsRect);
  449.                     }
  450.                     break;
  451.                 case inGrow:
  452.                     if ((GetMMWindow() != NULL) && (target != FrontWindow())) {
  453.                         SysBeep(1);
  454.                     } else if (gGrowWindow)
  455.                         gGrowWindow(target, ev->where, ev->modifiers);
  456.                     break;
  457.                 case inContent:
  458.                     if ((GetMMWindow() != NULL) && (target != FrontWindow())) {
  459.                         SysBeep(1);
  460.                     } else {
  461.                         Point pt;
  462.                         if (target != FrontWindow())
  463.                             SelectWindow(target);
  464.                         else {
  465.                             SetPort(target);
  466.                             if (ev->when - gLastClickTime <= GetDblTime()) gClickCounter++; else gClickCounter = 1;
  467.                             pt = ev->where;
  468.                             GlobalToLocal(&pt);
  469.                             if (gClickWindow) gClickWindow(target, pt, gClickCounter, ev->modifiers);
  470.                         }
  471.                     }
  472.                     break;
  473.                 case inZoomIn:
  474.                 case inZoomOut:
  475.                     if (gZoomWindow) 
  476.                         gZoomWindow(target, part_code, ev->modifiers);
  477.                     break;
  478.  
  479.             }
  480.             break;
  481.         case activateEvt:
  482.             target = (WindowPtr) (ev->message);
  483.             activate = ((ev->modifiers&1) != 0);
  484.             if (gActivateWindow) {
  485.                 gActivateWindow(target, activate);
  486.                 if (activate) gTheActiveWindow = target;
  487.             }
  488.             break;
  489.         case updateEvt:
  490.             target = (WindowPtr) (ev->message);
  491.             SetPort(target);
  492.             if (gUpdateWindow)
  493.                 gUpdateWindow(target);
  494.             else {
  495.                 BeginUpdate(target);
  496.                 EndUpdate(target);
  497.             }
  498.             break;
  499.         case kHighLevelEvent:
  500.             if (gAPPLEVENTS) AEProcessAppleEvent(ev);
  501.             break;
  502.     }
  503. }
  504.  
  505. Boolean CSAppGetEvent(EventRecord *ev, long sleep) {
  506.     Boolean got_event;
  507.     got_event = false;
  508.     if (gWNE) {
  509.         if (!WaitNextEvent(everyEvent, ev,  (sleep > GetCaretTime() ? GetCaretTime() : sleep), NULL))
  510.             ev->what = nullEvent;
  511.         else got_event = true;
  512.     } else {
  513.         SystemTask();
  514.         if (!GetNextEvent(everyEvent, ev)) ev->what = nullEvent; else got_event = true;
  515.     }
  516.     return got_event;
  517. }
  518.  
  519. Boolean RunCSApp(long sleep) {
  520.     EventRecord ev;
  521.     Boolean got_event;
  522.     got_event = CSAppGetEvent(&ev, sleep);
  523.     CSAppEvent(&ev);
  524.     return got_event;
  525. }
  526.  
  527.  
  528. OSErr OpenCSApp(long stack_kilobytes, long masterblocks) {
  529.     long response;
  530.     long i;
  531.     OSErr err;
  532.     if (stack_kilobytes >= 0) {
  533.         SetApplLimit(GetApplLimit() - (stack_kilobytes*1024));
  534.         if ((err = MemError()) != noErr) return err;
  535.         MaxApplZone();
  536.     }
  537.     for (i=0; i<masterblocks; i++) {
  538.         MoreMasters();
  539.         if ((err = MemError()) != noErr) return err;
  540.     }
  541.     InitGraf(&qd.thePort);
  542.     InitFonts();
  543.     InitWindows();
  544.     TEInit();
  545.     InitMenus();
  546.     InitDialogs(0);
  547.     FlushEvents(everyEvent, 0);
  548.     InitCursor();
  549.     gWNE = TrapAvail(_WaitNextEvent);
  550.     if (Gestalt(gestaltAppleEventsAttr, &response) != noErr) response = 0;
  551.     gAPPLEVENTS = ((response & (1<<gestaltAppleEventsPresent)) != 0);
  552.     return noErr;
  553. }
  554.  
  555. void CloseCSApp(void) {
  556.     ExitToShell();
  557. }
  558.